package com.hz.pro.kitchen.aspect;

import com.alibaba.fastjson.JSON;
import com.hz.pro.kitchen.annotation.HttpLog;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;

/**
 *
 */
@Component
@Aspect
@Slf4j
public class HttpLogAspect {
    @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping) " +
            "|| @annotation(org.springframework.web.bind.annotation.PostMapping)" +
            "|| @annotation(org.springframework.web.bind.annotation.GetMapping)")
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        boolean flag = false;
        Class clazz = null;
        Method method = null;
        try {
            MethodSignature signature = ((MethodSignature) pjp.getSignature());
            method = signature.getMethod();
            clazz = signature.getDeclaringType();
            flag = method.getAnnotation(HttpLog.class) != null || clazz.getAnnotation(HttpLog.class) != null;
            if (flag) {
                logRequest();
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        if (!flag) {
            return pjp.proceed();
        }
        long startTime = System.currentTimeMillis();
        Object obj = pjp.proceed();
        try {
            logResponse(obj, clazz, method, System.currentTimeMillis() - startTime);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return obj;
    }

    private void logResponse(Object object, Class clazz, Method method, long executeTime) {
        log.info("handler:{}:{}() -------controllerExecuteTime:{} \nresponse body:{}", clazz.getTypeName(), method.getName(), executeTime, JSON.toJSONString(object));
    }

    private void logRequest() {
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        HttpServletRequest req = ((ServletRequestAttributes) ra).getRequest();
        StringBuilder sb = new StringBuilder("\n");
        sb.append("url: ").append(req.getRequestURL()).append("\n");
        sb.append("params:\n");
        for (String name : req.getParameterMap().keySet()) {
            sb.append(name).append("=").append(req.getParameter(name)).append("\n");
        }
        log.info(sb.toString());
    }
}
